package org.jsola.hr.provider.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsola.cache.ICache;
import org.jsola.common.DateKit;
import org.jsola.common.PageKit;
import org.jsola.common.StrKit;
import org.jsola.common.TreeKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.core.entity.BaseDeleteDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.wechat.MessageHandlerUtil;
import org.jsola.hr.constant.ConfigCodeConstants;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ICompanyDAO;
import org.jsola.hr.dao.IEmpInfoDAO;
import org.jsola.hr.dto.EmpModifyPhoneAddDTO;
import org.jsola.hr.dto.UserRoleCompanyAddDTO;
import org.jsola.hr.dto.WeChatBindFromOffAccountDTO;
import org.jsola.hr.dto.user.AddUserDTO;
import org.jsola.hr.dto.user.UpdateUserRoleDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.*;
import org.jsola.hr.query.ChannelQuery;
import org.jsola.hr.query.HrRoleQuery;
import org.jsola.hr.query.HrUserQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.message.dto.WeiXinDTO;
import org.jsola.message.dto.WxMiNiParam;
import org.jsola.message.dto.WxTemplateParam;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.notice.dto.NoticeRuleSettingUpdateDTO;
import org.jsola.notice.entity.NoticeRuleSettingDO;
import org.jsola.permission.constant.PermissionConstants;
import org.jsola.permission.dto.RoleMemberAddDTO;
import org.jsola.permission.entity.RoleDO;
import org.jsola.permission.query.RoleMemberQuery;
import org.jsola.permission.service.IRoleService;
import org.jsola.permission.vo.RoleMemberListVO;
import org.jsola.user.common.CacheKeyKit;
import org.jsola.user.constant.UserConstants;
import org.jsola.user.core.TokenUser;
import org.jsola.user.core.UserContext;
import org.jsola.user.dao.IThirdInfoDAO;
import org.jsola.user.dto.*;
import org.jsola.user.dto.login.WechatWebLoginDTO;
import org.jsola.user.dto.login.WechatXcxLoginDTO;
import org.jsola.user.entity.*;
import org.jsola.user.query.LoginLogQuery;
import org.jsola.user.query.UserQuery;
import org.jsola.user.service.*;
import org.jsola.user.vo.SystemConfigVO;
import org.jsola.user.vo.UserListVO;
import org.jsola.user.vo.UserLoginVO;
import org.jsola.user.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrConstants.JIA_FANG_USER_CODE;
import static org.jsola.hr.constant.HrPermissionConstants.*;
import static org.jsola.hr.constant.HrPermissionConstants.HR_DEFAULT_SUBJECT_ID;
import static org.jsola.user.constant.UserConstants.*;

/**
 * @author JanusMix
 */
@Slf4j
@Service("hrUserProviderService")
public class UserProviderServiceImpl implements IUserProviderService {

    @Autowired
    private ILoginService loginService;
    @Lazy
    @Autowired
    private IChannelService channelService;

    @Autowired
    @Lazy
    private ISaleUserService saleUserService;

    @Autowired
    private IPermissionProviderService permissionProviderService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserSiteMapperService userSiteMapperService;

    @Autowired
    private IUserSiteService userSiteService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpInfoDAO empInfoDAO;

    @Autowired
    private IThirdInfoService thirdInfoService;

    @Autowired
    private ICompanyDAO companyDAO;

    @Autowired
    private IChildCompanyService childCompanyService;

    @Autowired
    private IUnionOpenIdService unionOpenIdService;

    @Autowired
    private ITokenService tokenService;

    @Autowired
    private IUserRoleCompanyService userRoleCompanyService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private ISystemConfigService systemConfigService;

    @Autowired
    private IThirdInfoDAO thirdInfoDAO;

    @Autowired
    private MessageHandlerUtil messageHandlerUtil;

    @Autowired
    private IMessageProviderService messageProviderService;

    @Autowired
    private INameVerifiedService nameVerifiedService;

    @Autowired
    private ISiteConfigProviderService siteConfigProviderService;

    @Autowired
    private ICache cache;

    @Autowired
    private IHrPermissionService hrPermissionService;

    @Autowired
    private IHrRoleService hrRoleService;

    @Autowired
    private IWechatService wechatService;

    @Autowired
    private IEmpSocBackResponsibleService empSocBackResponsibleService;

    @Autowired
    private IEmpModifyPhoneService empModifyPhoneService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private ILoginLogService loginLogService;

    @Autowired
    private IGroupCompanyService groupCompanyService;

    @Autowired
    private ICertificationHistoryService certificationHistoryService;

    @Autowired
    private ICertificationService certificationService;

    @Autowired
    private INoticeProviderService noticeProviderService;

    /**
     * 微信的头像url
     */
    private static final String AVATAR_WECHAT_URL = "thirdwx.qlogo.cn";

    @Override
    public List<UserListVO> select(UserQuery userQuery) {
        return userService.select(userQuery);
    }

    @Override
    public EmpLoginResultVO wechatXcxLogin(WechatXcxLoginDTO wechatXcxLoginDTO) {
        EmpLoginResultVO empLoginResultVO = new EmpLoginResultVO();
        // 用户微信登录（成功返回userId，都会返回unionId）
        log.info("微信小程序登录参数：{}", wechatXcxLoginDTO);
        UserLoginVO userLoginVO = loginService.wechatXcxLogin2(wechatXcxLoginDTO);
        log.info("userLoginVO：{}", userLoginVO);
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfoDOTmp = thirdInfoService.selectByUnionId(userLoginVO.getUnionId());
        log.info("微信登录thirdInfoDOTmp：{}", thirdInfoDOTmp);
        if (Objects.nonNull(thirdInfoDOTmp)) {
            empLoginResultVO.setHeadImgUrl(thirdInfoDOTmp.getHeadImgUrl());
            empLoginResultVO.setNickName(thirdInfoDOTmp.getNickName());
        }
        empLoginResultVO.setUserLoginVO(userLoginVO);
        if (userLoginVO.getVerified()) {
            // 用户登录成功，根据用户ID查询员工信息
            Example example = new Example(EmpInfoDO.class);
            example.and()
                    .andEqualTo("valid", true)
                    .andEqualTo("userId", userLoginVO.getUserVO().getId());
            // 2021-11-26 待入职员工也可进入小程序，该筛选条件无用，暂时取消
            //.andIn("status", Arrays.asList(1, 2, 3, 4));
            example.orderBy("gmtCreate");
            List<EmpInfoDO> empInfoDOList = empInfoDAO.selectByExample(example);
            //有在职员工
            if (!CollectionUtils.isEmpty(empInfoDOList)) {
                EmpInfoDO empInfoDO = null;
                //找到与登录租户相同的员工
                for (EmpInfoDO empInfoDOTmp : empInfoDOList) {
                    if (empInfoDOTmp.getSiteId().equals(userLoginVO.getSiteId())) {
                        empInfoDO = empInfoDOTmp;
                        break;
                    }
                }
                // 当前登录用户的租户下没有员工，则切换到有员工的租户下
                if (Objects.isNull(empInfoDO)) {
                    empInfoDO = empInfoDOList.get(0);
                    log.info("站点下不存在员工，切换租户到：" + empInfoDO.getSiteId());
                    // 切换到当前员工用户的租户下，即登录到另一个站点
                    JwtTokenDTO jwtTokenDTO = tokenService.switchToken(userLoginVO.getJwtTokenDTO().getToken(), empInfoDO.getSiteId());
                    userLoginVO.setSiteId(empInfoDO.getSiteId());
                    userLoginVO.setJwtTokenDTO(jwtTokenDTO);
                }
                log.info("员工所在公司:" + empInfoDO.getCompanyId());
                CompanyDO companyDO = companyDAO.selectByPrimaryKey(empInfoDO.getCompanyId());
                if (empInfoDO.getUnionId() == null) {
                    empInfoDO.setUnionId(userLoginVO.getUnionId());
                    empInfoService.updateByIdSelective(empInfoDO, empInfoDO.getSiteId(), empInfoDO.getCreateUserId());
                }
                EmpAllInfoVO empAllInfoVO = empInfoDO.to(EmpAllInfoVO.class);
                empAllInfoVO.setCompanyName(companyDO.getName());
                empLoginResultVO.setEmpAllInfoVO(empAllInfoVO);
                //更新emp_info头像
                if (StringUtils.isNotBlank(empLoginResultVO.getHeadImgUrl()) &&
                        StringUtils.isEmpty(empInfoDO.getEmpPhoto())) {
                    EmpInfoDO updatePhote = new EmpInfoDO();
                    updatePhote.setId(empInfoDO.getId());
                    updatePhote.setEmpPhoto(empLoginResultVO.getHeadImgUrl());
                    empInfoService.updateByIdSelective(updatePhote);
                }
            }
        }
        log.info("微信登录返回信息：{}", empLoginResultVO);
        return empLoginResultVO;
    }

    @Override
    public EmpLoginResultVO wechatXcxLoginForAdmin(WechatXcxLoginDTO wechatXcxLoginDTO) {
        EmpLoginResultVO empLoginResultVO = new EmpLoginResultVO();
        // 用户微信登录（成功返回userId，都会返回unionId）
        log.info("微信小程序登录参数：{}", wechatXcxLoginDTO);
        UserLoginVO userLoginVO = loginService.wechatXcxLogin2(wechatXcxLoginDTO);
        log.info("userLoginVO：{}", userLoginVO);
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfoDOTmp = thirdInfoService.selectByUnionId(userLoginVO.getUnionId());
        log.info("微信登录thirdInfoDOTmp：{}", thirdInfoDOTmp);
        if (Objects.nonNull(thirdInfoDOTmp)) {
            empLoginResultVO.setHeadImgUrl(thirdInfoDOTmp.getHeadImgUrl());
            empLoginResultVO.setNickName(thirdInfoDOTmp.getNickName());
        }
        empLoginResultVO.setUserLoginVO(userLoginVO);
        log.info("微信登录返回信息：{}", empLoginResultVO);
        return empLoginResultVO;
    }


    @Override
    public String getPhone(WechatXcxLoginDTO wechatXcxLoginDTO) {
        String deviceType = UserContext.getDeviceType();
        //先拿code换取sessionKey,如果没有unionId,从解密用户信息里取,否则直接查询数据库
        ThirdLoginDTO thirdLoginDTO = wechatService.getSessionKeyByCode(wechatXcxLoginDTO.getJsCode(), deviceType);
        wechatXcxLoginDTO.setSessionKey(thirdLoginDTO.getSessionKey());
        // 通过加密字符串获取手机号
        PhoneNumberDTO phoneNoInfo = wechatService.getPhoneInfoByEncrypt(wechatXcxLoginDTO, deviceType);
        log.info("小程序授权解析手机号：{}，完整信息：{}", phoneNoInfo.getPhoneNumber(), phoneNoInfo);
        return phoneNoInfo.getPhoneNumber();
    }

    @Override
    @Transactional(value = UserConstants.TX, rollbackFor = Exception.class)
    public RecruitResultVO wechatRecruitLogin(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO) {
        RecruitResultVO recruitResultVO = new RecruitResultVO();
        // 用户微信登录（成功返回userId，都会返回unionId）
        UserLoginVO userLoginVO = wechatRecruit2Login(recruitWechatXcxLoginDTO);
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfoDOTmp = thirdInfoService.selectByUnionId(userLoginVO.getUnionId());
        if (Objects.nonNull(thirdInfoDOTmp)) {
            recruitResultVO.setHeadImgUrl(thirdInfoDOTmp.getHeadImgUrl());
            recruitResultVO.setNickName(thirdInfoDOTmp.getNickName());
        }
        recruitResultVO.setUserLoginVO(userLoginVO);
        return recruitResultVO;
    }


    /**
     * 招聘小程序登录
     *
     * @param recruitWechatXcxLoginDTO recruitWechatXcxLoginDTO
     * @return UserLoginVO
     */
    @Deprecated
    private UserLoginVO wechatRecruit2Login(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO) {
        // 设备类型
        String deviceType = UserContext.getDeviceType();
        //返回对象
        UserLoginVO userLoginVO = new UserLoginVO();
        String unionId;
        // 手机号
        String phone = recruitWechatXcxLoginDTO.getPhone();
        // 登录站点
        String siteId = recruitWechatXcxLoginDTO.getSiteId();
        // 登录端
        String terminalType = recruitWechatXcxLoginDTO.getTerminalType();
        //先拿code换取sessionKey,如果没有unionId,从解密用户信息里取,否则直接查询数据库
        ThirdLoginDTO thirdLoginDTO = wechatService.getSessionKeyByCode(recruitWechatXcxLoginDTO.getJsCode(), deviceType);
        recruitWechatXcxLoginDTO.setSessionKey(thirdLoginDTO.getSessionKey());
        recruitWechatXcxLoginDTO.setUnionId(thirdLoginDTO.getUnionId());
        ThirdInfoDO thirdInfoDO = wechatService.getUserInfoByEncrypt2(recruitWechatXcxLoginDTO, deviceType);
        if (StringUtils.isEmpty(thirdLoginDTO.getUnionId())) {
            unionId = thirdInfoDO.getUnionId();
            log.info("未获取用户的unionId:{},通过解密获取userThirdInfoDO：{}", recruitWechatXcxLoginDTO, thirdInfoDO);
        } else {
            unionId = thirdLoginDTO.getUnionId();
        }
        userLoginVO.setUnionId(unionId);
        // 数据库里的第三方用户信息
        ThirdInfoDO dbThirdInfoDO = thirdInfoService.selectByUnionId(unionId);
        // 数据库没有就是没有授权过，、通过手机号查询用户信息 没有就新建
        if (Objects.isNull(dbThirdInfoDO)) {
            // 保存三方信息
            thirdInfoDO.setUnionId(unionId);
            dbThirdInfoDO = thirdInfoService.save(thirdInfoDO, DEFAULT_SITE_ID, DEFAULT_USER_ID);
        }
        UserVO userVO;
        if (StrKit.isEmpty(dbThirdInfoDO.getUserId())) {
            UserDO userDO = userService.selectByPhone(phone);
            if (userDO == null) {
                userVO = creatUser(phone, siteId);
            } else {
                userVO = userDO.to(UserVO.class);
            }
        } else {
            // 三方信息中心含有用户Id 去用户表查询 查不到就新建 后更三方中的用户Id
            String userId = dbThirdInfoDO.getUserId();
            UserDO userDO = userService.selectDOById(userId);
            if (userDO == null) {
                userVO = creatUser(phone, siteId);
            } else {
                userVO = userDO.to(UserVO.class);
            }
        }
        thirdInfoDO.setUserId(userVO.getId());
        //更新第三方信息
        ThirdInfoUpdateDTO thirdInfoUpdateDTO = thirdInfoDO.to(ThirdInfoUpdateDTO.class);
        thirdInfoUpdateDTO.setId(dbThirdInfoDO.getId());
        //微信绑定的用户id
        thirdInfoService.update(thirdInfoUpdateDTO, buildSystemUser());
        //保存认证历史
        certificationHistoryService.saveIfNotExist(this.buildCertification(dbThirdInfoDO.getId().toString()
                , CERTIFICATION_TYPE_THIRD, userVO.getId()));
        //登录
        return commonLogin(userVO, thirdInfoDO.getHeadImgUrl(), deviceType, terminalType, siteId, LOGIN_LOG_TYPE_WECHAT);
    }

    /**
     * 根据手机号和站点创建用户
     *
     * @param phone  手机号
     * @param siteId 站点Id
     * @return 用户信息
     */
    private UserVO creatUser(String phone, String siteId) {
        TokenUser createUser = new TokenUser();
        createUser.setSiteId(siteId);
        createUser.setUserId("system");
        //用户不存在
        UserAddDTO userAddDTO = new UserAddDTO();
        userAddDTO.setPhone(phone);
        userAddDTO.setName(phone);
        //注册用户
        return userService.save(userAddDTO, createUser);
    }

    /**
     * 标准登录逻辑
     *
     * @param userVO       用户信息
     * @param headImgUrl   第三方头像
     * @param deviceType   设备类型
     * @param terminalType 登录终端，toB toC
     * @param siteId       登录站点
     * @param loginType    登录方式
     * @return 登录展示信息
     */
    private UserLoginVO commonLogin(UserVO userVO, String headImgUrl, String deviceType, String terminalType, String siteId, Integer loginType) {
        UserLoginVO userLoginVO = new UserLoginVO();
        String userId = userVO.getId();
        //登录日志
        LoginLogDO loginLogDO = new LoginLogDO(userId);
        loginLogDO.setType(loginType);

        UserSiteDO userSiteDO = userSiteService.selectByUserIdAndSiteId(userId, siteId, TO_C);
        // 用户站点不存在 创建
        if (!DEFAULT_SITE_ID.equals(siteId) && userSiteDO == null) {
            TokenUser tokenUser = new TokenUser();
            tokenUser.setUserId(userId);
            tokenUser.setSiteId(siteId);
            UserSiteAddDTO userSiteAddDTO = new UserSiteAddDTO();
            userSiteAddDTO.setUserId(userId);
            userSiteAddDTO.setUserSiteId(siteId);
            userSiteAddDTO.setStatus(ON_JOB.intValue());
            userSiteAddDTO.setTerminalType(TO_C);
            userSiteService.save(userSiteAddDTO, tokenUser);
        }

        //Step3：已绑定，如果用户用的微信头像则修改头像
        boolean updateWechatAvatar = StringUtils.isBlank(userVO.getAvatar())
                || (!StringUtils.isBlank(userVO.getAvatar()) && userVO.getAvatar().contains(AVATAR_WECHAT_URL));
        if (!StringUtils.isBlank(headImgUrl) && updateWechatAvatar) {
            //更新头像
            UserUpdateDTO userUpdateDTO = new UserUpdateDTO();
            userUpdateDTO.setId(userId);
            userUpdateDTO.setAvatar(headImgUrl);
            userService.update(userUpdateDTO, buildSystemUser());
            userVO.setAvatar(headImgUrl);
        }

        //Step4：将token放入返回对象
        userLoginVO.setJwtTokenDTO(tokenService.createToken(buildTokenUser(userVO, siteId, deviceType, loginType)));
        userLoginVO.setSiteName(siteId);
        userLoginVO.setSiteId(siteId);
        userLoginVO.setUserVO(userVO);
        userLoginVO.setDimission(Boolean.FALSE);

        //Step5：保存登录日志
        loginLogDO.setUserName(userVO.getName());
        loginLogDO.setUserAvatar(userVO.getAvatar());
        loginLogDO.setIsSuccess(Boolean.TRUE);
        loginLogDO.setTerminalType(terminalType);
        loginLogService.save(loginLogDO, siteId, DEFAULT_USER_ID);

        return userLoginVO;
    }

    /**
     * 构建系统修改用户
     *
     * @return 系统修改用户
     */
    private TokenUser buildSystemUser() {
        //系统修改用户
        TokenUser updateUser = new TokenUser();
        updateUser.setSiteId(DEFAULT_SITE_ID);
        updateUser.setUserId(DEFAULT_USER_ID);
        return updateUser;
    }

    /**
     * 构造认证历史对象
     *
     * @param account 第三方表id
     * @param type    认证类型
     * @param userId  用户id
     * @return 认证历史对象
     */
    private CertificationHistoryDO buildCertification(String account, Integer type, String userId) {
        CertificationHistoryDO certificationHistoryDO = new CertificationHistoryDO();
        certificationHistoryDO.setType(type);
        certificationHistoryDO.setAccount(account);
        certificationHistoryDO.setUserId(userId);
        certificationHistoryDO.setSiteId(DEFAULT_SITE_ID);
        return certificationHistoryDO;
    }

    /**
     * 构造生成token的TokenUser
     *
     * @param userVO     用户对象
     * @param siteId     站点id
     * @param deviceType 设备类型
     * @return TokenUser
     */
    private TokenUser buildTokenUser(UserVO userVO, String siteId, String deviceType, Integer loginType) {
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId(userVO.getId());
        tokenUser.setUserName(userVO.getName());
        tokenUser.setSiteId(siteId);
        tokenUser.setSiteName(siteId);
        tokenUser.setDeviceType(deviceType);
        tokenUser.setLoginType(loginType);
        tokenUser.setAvatar(userVO.getAvatar());
        return tokenUser;
    }

    @Override
    @Transactional(value = UserConstants.TX, rollbackFor = Exception.class)
    public RecruitResultVO wechatRecruitLogin2(RecruitWechatXcxLoginDTO recruitWechatXcxLoginDTO) {
        RecruitResultVO recruitResultVO = new RecruitResultVO();
        // 用户微信登录（成功返回userId，都会返回unionId）
        // 设备类型
        String deviceType = UserContext.getDeviceType();
        // 登录端
        String terminalType = recruitWechatXcxLoginDTO.getTerminalType();
        //先拿code换取sessionKey,如果没有unionId,从解密用户信息里取,否则直接查询数据库
        ThirdLoginDTO thirdLoginDTO = wechatService.getSessionKeyByCode(recruitWechatXcxLoginDTO.getJsCode(), deviceType);
        recruitWechatXcxLoginDTO.setSessionKey(thirdLoginDTO.getSessionKey());
        String unionId = thirdLoginDTO.getUnionId();
        recruitWechatXcxLoginDTO.setUnionId(unionId);
        ThirdInfoDO thirdInfoDO = wechatService.getUserInfoByEncrypt2(recruitWechatXcxLoginDTO, deviceType);
        // 招聘登录 若无指定登录站点 取默认站点
        String siteId = recruitWechatXcxLoginDTO.getSiteId();
        if (StringUtil.isBlank(siteId)) {
            siteId = DEFAULT_SITE_ID;
        }
        UserLoginVO userLoginVO = wechatRecruit2Login2(thirdInfoDO, terminalType, unionId, siteId);
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfoDoTmp = thirdInfoService.selectByUnionId(userLoginVO.getUnionId());
        if (Objects.isNull(thirdInfoDoTmp)) {
            // 保存三方信息
            thirdInfoDO.setUnionId(unionId);
            thirdInfoDoTmp = thirdInfoService.save(thirdInfoDO, DEFAULT_SITE_ID, DEFAULT_USER_ID);
        }
        recruitResultVO.setHeadImgUrl(thirdInfoDoTmp.getHeadImgUrl());
        recruitResultVO.setNickName(thirdInfoDoTmp.getNickName());
        recruitResultVO.setUserLoginVO(userLoginVO);
        return recruitResultVO;
    }

    /**
     * 构成登陆对象
     *
     * @param thirdInfoDO  微信登录信息
     * @param terminalType 终端类型
     * @param unionId      微信唯一标识
     * @param siteId       站点Id
     * @return 登陆对象
     */
    private UserLoginVO wechatRecruit2Login2(ThirdInfoDO thirdInfoDO, String terminalType, String unionId, String siteId) {
        // 设备类型
        String deviceType = UserContext.getDeviceType();
        TokenUser buildSystemUser = buildSystemUser();
        //返回对象
        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setUnionId(unionId);
        // 数据库里的第三方用户信息
        ThirdInfoDO dbThirdInfoDO = thirdInfoService.selectByUnionId(unionId);
        // 数据库没有就是没有授权过，保存到第三方用户表，然后返回失败
        if (Objects.isNull(dbThirdInfoDO)) {
            // 保存三方信息
            thirdInfoDO.setUnionId(unionId);
            thirdInfoService.save(thirdInfoDO, DEFAULT_SITE_ID, DEFAULT_USER_ID);
            userLoginVO.setVerified(Boolean.FALSE);
            return userLoginVO;
        }
        //更新第三方信息
        thirdInfoService.updateByIdSelective(thirdInfoDO, buildSystemUser.getSiteId(), buildSystemUser.getUserId());

        //未绑定用户，返回验证失败
        String userId = dbThirdInfoDO.getUserId();
        if (StrKit.isEmpty(userId)) {
            userLoginVO.setVerified(Boolean.FALSE);
            return userLoginVO;
        }
        UserDO userDO = userService.selectDOById(userId);
        // 用户被删除
        if (userDO == null) {
            // 删除三方信息中用户信息 返回验证失败
            dbThirdInfoDO.setUserId(null);
            thirdInfoService.updateById(dbThirdInfoDO, buildSystemUser.getSiteId(), buildSystemUser.getUserId());
            userLoginVO.setVerified(Boolean.FALSE);
            return userLoginVO;
        }
        UserVO userVO = userDO.to(UserVO.class);
        //保存认证历史
        certificationHistoryService.saveIfNotExist(this.buildCertification(dbThirdInfoDO.getId().toString()
                , CERTIFICATION_TYPE_THIRD, userId));
        //登录
        return commonLogin(userVO, thirdInfoDO.getHeadImgUrl(), deviceType, terminalType, siteId, LOGIN_LOG_TYPE_WECHAT);
    }


    @Override
    public EmpLoginResultVO wechatWebLogin(WechatWebLoginDTO wechatWebLoginDTO) {
        EmpLoginResultVO empLoginResultVO = new EmpLoginResultVO();
        // 用户微信登录（成功返回userId，都会返回unionId）
        UserLoginVO userLoginVO = loginService.wechatWebLogin(wechatWebLoginDTO);
        // 根据unionId获取第三方信息
        ThirdInfoDO thirdInfoDOTmp = thirdInfoService.selectByUnionId(userLoginVO.getUnionId());
        if (Objects.nonNull(thirdInfoDOTmp)) {
            empLoginResultVO.setHeadImgUrl(thirdInfoDOTmp.getHeadImgUrl());
            empLoginResultVO.setNickName(thirdInfoDOTmp.getNickName());
        }

        empLoginResultVO.setUserLoginVO(userLoginVO);
        //登录成功
        if (userLoginVO.getVerified()) {
            // 用户登录成功，根据用户ID查询员工信息
            Example example = new Example(EmpInfoDO.class);
            example.and()
                    .andEqualTo("valid", true)
                    .andEqualTo("userId", userLoginVO.getUserVO().getId())
                    .andIn("status", Arrays.asList(2, 3));
            List<EmpInfoDO> empInfoDOList = empInfoDAO.selectByExample(example);
            //有在职员工
            if (!CollectionUtils.isEmpty(empInfoDOList)) {
                //找到与登录租户相同的员工
                EmpInfoDO empInfoDO = null;
                for (EmpInfoDO empInfoDOTmp : empInfoDOList) {
                    if (empInfoDOTmp.getSiteId().equals(userLoginVO.getSiteId())) {
                        empInfoDO = empInfoDOTmp;
                    }
                }
                // 当前登录用户的租户下没有员工，则切换到有员工的租户下
                if (!Objects.nonNull(empInfoDO)) {
                    empInfoDO = empInfoDOList.get(0);
                    // 切换到当前员工用户的租户下，即登录到另一个站点
                    JwtTokenDTO jwtTokenDTO = tokenService.switchToken(userLoginVO.getJwtTokenDTO().getToken(), empInfoDO.getSiteId());
                    userLoginVO.setJwtTokenDTO(jwtTokenDTO);
                }
                CompanyDO companyDO = companyDAO.selectByPrimaryKey(empInfoDO.getCompanyId());
                if (empInfoDO.getUnionId() == null) {
                    empInfoDO.setUnionId(userLoginVO.getUnionId());
                    empInfoDO.setEmpPhoto(empLoginResultVO.getHeadImgUrl());
                    empInfoService.updateByIdSelective(empInfoDO, empInfoDO.getSiteId(), empInfoDO.getCreateUserId());
                }
                EmpAllInfoVO empAllInfoVO = empInfoDO.to(EmpAllInfoVO.class);
                empAllInfoVO.setCompanyName(companyDO.getName());
                empLoginResultVO.setEmpAllInfoVO(empAllInfoVO);
            }
        }
        return empLoginResultVO;
    }

    @Override
    public UserLoginVO bindWechatAndLogin(String userId, String terminalType, String unionId) {
        return loginService.bindWechatAndLogin(userId, terminalType, unionId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public HrUserVO saveUser(AddUserDTO addUserDTO, TokenUser tokenUser) {
        HrRoleVO hrRoleVO = hrRoleService.selectById(addUserDTO.getHrRoleId(), tokenUser.getSiteId());
        ParamException.notNull(hrRoleVO, "人力角色信息有误，请查证后再试");
        String[] split = hrRoleVO.getRoleIds().split(",");
        List<RoleDO> roleDOList = permissionProviderService.selectRoleByIds(Arrays.stream(split)
                .map(Long::parseLong).collect(Collectors.toList()), tokenUser.getSiteId());
        Long roleId = null;
        Long subjectId = null;
        for (RoleDO roleDO : roleDOList) {
            // 操作端角色
            if (COMPANY_SUBJECT_TYPE.equals(roleDO.getSubjectType())) {
                roleId = roleDO.getId();
            }
            // 管理端角色
            if (HR_SUBJECT_TYPE.equals(roleDO.getSubjectType())) {
                subjectId = roleDO.getId();
            }
        }
        ParamException.notNull(roleId, "操作端角色信息有误，请查证后再试");
        ParamException.notNull(subjectId, "管理端角色信息有误，请查证后再试");
        addUserDTO.setRoleId(roleId);
        HrUserVO user;
        UserDO existUser = userService.selectByPhone(addUserDTO.getPhone());
        //是否已有此员工，有了就只往userSite表中插一条数据
        if (Objects.isNull(existUser)) {
            UserAddDTO userAddDTO = new UserAddDTO();
            userAddDTO.setPhone(addUserDTO.getPhone());
            userAddDTO.setEmail(addUserDTO.getMailbox());
            userAddDTO.setName(addUserDTO.getName());
            userAddDTO.setAvatar("");
            userAddDTO.setPassword(addUserDTO.getPassword());
            userAddDTO.setIsReadOnly(addUserDTO.getIsReadOnly());
            userAddDTO.setEmail(addUserDTO.getEmail());
            //保存用户
            UserVO userVO = userSiteMapperService.save(userAddDTO, tokenUser);
            user = userVO.to(HrUserVO.class);
        } else {
            updateUserPassword(existUser.getId(), addUserDTO.getPassword(), tokenUser);
            UserSiteDO userSiteDO = userSiteService.selectByUserIdAndSiteId(existUser.getId(), tokenUser.getSiteId(), TO_B);
            if (Objects.nonNull(userSiteDO)) {
                if (userSiteDO.getStatus() == OFF_JOB.intValue()) {
                    throw new ParamException("员工已离职，请删除后再试");
                }
            } else {
                //保存userSite表
                this.saveUserSite(existUser.getId(), tokenUser);
            }
            //更新用户的用户名
            UserUpdateDTO userUpdateDTO = new UserUpdateDTO();
            userUpdateDTO.setId(existUser.getId());
            userUpdateDTO.setName(addUserDTO.getName());
            //更新只读状态
            userUpdateDTO.setIsReadOnly(addUserDTO.getIsReadOnly());
            userService.update(userUpdateDTO, tokenUser);
            existUser.setName(addUserDTO.getName());
            user = existUser.to(HrUserVO.class);
        }
//        ParamException.isFalse(tokenUser.getUserId().equals(user.getId()), "不能添加自己的权限，请联系其他管理员");
        //添加角色成员
        // 先删除就得角色权限 再创建新的角色
        updateRole(addUserDTO.getRoleId(), user.getId(), tokenUser);
        // 公司分组Ids
        List<String> childCompanyIdList = addUserDTO.getChildCompanyIdList();
        // 添加用户在某分公司下有权限的用工单位
        userRoleCompanyService.add(user.getId(), addUserDTO.getRoleId(), addUserDTO.getIsAllChildCompany()
                , childCompanyIdList, addUserDTO.getEmployerIdList(), tokenUser);

        // 管理端角色创建
        RoleMemberAddDTO roleMemberAddDTO = new RoleMemberAddDTO();
        roleMemberAddDTO.setMemberId(user.getId());
        roleMemberAddDTO.setRoleId(subjectId);
        roleMemberAddDTO.setSubjectId("0");
        roleMemberAddDTO.setSubjectType(HR_SUBJECT_TYPE);
        roleMemberAddDTO.setType("U");
        permissionProviderService.deleteRoleMember(user.getId(), null, HR_SUBJECT_TYPE, null, tokenUser.getSiteId());
        permissionProviderService.addRoleMemberBatch(Collections.singletonList(roleMemberAddDTO), tokenUser);
        List<String> employerIdList = addUserDTO.getEmployerIdList();
        if (addUserDTO.getIsAllChildCompany() != null && addUserDTO.getIsAllChildCompany()) {
            List<CompanyDO> siteCompanyList = companyService.selectBySiteId(tokenUser.getSiteId());
            List<String> siteCompanyIdList = siteCompanyList.stream().map(CompanyDO::getId).collect(Collectors.toList());
            employerIdList.addAll(siteCompanyIdList);
        }
        saveUserUpdateNotice(hrRoleVO, childCompanyIdList, employerIdList, user.getId(), tokenUser);
        return user;
    }

    @Override
    public void saveUserUpdateNotice(HrRoleVO hrRole, List<String> selectGroupIdList, List<String> selectCompanyIdList,
                                     String userId, TokenUser tokenUser) {
        if (JIA_FANG_USER_CODE.equals(hrRole.getCode())) {
            List<String> companyIdList = new ArrayList<>();
            // 先查询发送给这个人的消息通知
            List<NoticeRuleSettingDO> userNoticeList = noticeProviderService
                    .selectByUserId(HR_SUBJECT_TYPE, NoticeConstants.EVENT_HANDLING, userId);
            // 这个是用工单位分组Id 需要查询分组下的所有用工单位Id
            if (!CollectionUtils.isEmpty(selectGroupIdList)) {
                List<String> groupCompanyIdList = groupCompanyService
                        .selectCompanyIdsByGroupIds(selectGroupIdList, tokenUser.getSiteId());
                companyIdList.addAll(groupCompanyIdList);
            }
            if (!CollectionUtils.isEmpty(selectCompanyIdList)) {
                companyIdList.addAll(selectCompanyIdList);
            }
            // 把所有的用工单位Id合成一个List因为有重复的,去重
            if (!CollectionUtils.isEmpty(companyIdList)) {
                companyIdList = companyIdList.stream().distinct().collect(Collectors.toList());
            }
            // 查询这些用工单位的事件处理(服务反馈) 的消息通知
            List<NoticeRuleSettingDO> companyNoticeList = noticeProviderService
                    .selectByCompanyIdList(HR_SUBJECT_TYPE, NoticeConstants.EVENT_HANDLING, companyIdList);
            // 需要自动把当前添加的用户添加到这些用工单位的发送人里面
            if (!CollectionUtils.isEmpty(companyNoticeList)) {
                List<Long> filterNoticeIdList = new ArrayList<>();
                for (NoticeRuleSettingDO companyNotice : companyNoticeList) {
                    String sendUserStr = companyNotice.getUserIds();
                    // 如果当前用工单位的发送人里已经有这个用户了,跳过,并且记录通知设置id
                    if (!StringUtils.isEmpty(sendUserStr) && sendUserStr.contains(userId)) {
                        filterNoticeIdList.add(companyNotice.getId());
                        continue;
                    }
                    if (StringUtils.isEmpty(sendUserStr)) {
                        companyNotice.setUserIds(userId);
                        HrNoticeUserIdJsonVO hrNoticeUserIdJson = new HrNoticeUserIdJsonVO();
                        hrNoticeUserIdJson.setUserIds(userId);
                        companyNotice.setUserIdParam(JSON.toJSONString(hrNoticeUserIdJson));
                    } else {
                        sendUserStr = sendUserStr + "," + userId;
                        companyNotice.setUserIds(sendUserStr);
                        HrNoticeUserIdJsonVO hrNoticeUserIdJson = JSONObject
                                .parseObject(companyNotice.getUserIdParam(), HrNoticeUserIdJsonVO.class);
                        String userIdsParam = hrNoticeUserIdJson.getUserIds();
                        if (StringUtils.isEmpty(userIdsParam)) {
                            hrNoticeUserIdJson.setUserIds(userId);
                        } else {
                            userIdsParam = userIdsParam + "," + userId;
                            hrNoticeUserIdJson.setUserIds(userIdsParam);
                        }
                        companyNotice.setUserIdParam(JSON.toJSONString(hrNoticeUserIdJson));
                    }
                    noticeProviderService.update(companyNotice.to(NoticeRuleSettingUpdateDTO.class), tokenUser);
                }
                // 过滤已经有通知人的消息设置
                userNoticeList = userNoticeList.stream()
                        .filter(notice -> !filterNoticeIdList.contains(notice.getId()))
                        .collect(Collectors.toList());

            }
            // 把剩下的消息设置里的发送人去掉当前添加或修改的这个用户
            for (NoticeRuleSettingDO noticeRuleSetting : userNoticeList) {
                String userIds = noticeRuleSetting.getUserIds();
                noticeRuleSetting.setUserIds(filterUserId(userIds, userId));
                HrNoticeUserIdJsonVO hrNoticeUserIdJson = JSONObject
                        .parseObject(noticeRuleSetting.getUserIdParam(), HrNoticeUserIdJsonVO.class);
                String userIdsParam = hrNoticeUserIdJson.getUserIds();
                if (!StringUtils.isEmpty(userIdsParam) && userIdsParam.contains(userIds)) {
                    hrNoticeUserIdJson.setUserIds(filterUserId(userIdsParam, userId));
                }
                noticeRuleSetting.setUserIdParam(JSON.toJSONString(hrNoticeUserIdJson));
                noticeProviderService.update(noticeRuleSetting.to(NoticeRuleSettingUpdateDTO.class), tokenUser);
            }
        }
    }

    private String filterUserId(String userIds, String userId) {
        String[] userIdArray = userIds.split(",");
        List<String> userIdList = new ArrayList<>(Arrays.asList(userIdArray));
        return userIdList.stream()
                .filter(noticeUserId -> !userId.equals(noticeUserId))
                .collect(Collectors.joining(","));
    }

    @Override
    public UserVO saveChannelUser(AddUserDTO addUserDTO, TokenUser tokenUser) {

        // 根据手机号查询用户信息
        UserDO existUser = userService.selectByPhone(addUserDTO.getPhone());
        // 未查询到 新建
        if (Objects.isNull(existUser)) {
            UserAddDTO userAddDTO = new UserAddDTO();
            userAddDTO.setPhone(addUserDTO.getPhone());
            userAddDTO.setEmail(addUserDTO.getMailbox());
            userAddDTO.setName(addUserDTO.getName());
            userAddDTO.setAvatar("");
            userAddDTO.setPassword(addUserDTO.getPassword());
            userAddDTO.setEmail(addUserDTO.getEmail());
            //保存用户
            return userSiteMapperService.save(userAddDTO, tokenUser);
        }
        // 是否已有此员工，有了就只往userSite表中插一条数据
        UserSiteDO userSiteDO = userSiteService.selectByUserIdAndSiteId(existUser.getId(), tokenUser.getSiteId(), TO_B);
        if (Objects.isNull(userSiteDO)) {
            //保存userSite表
            this.saveUserSite(existUser.getId(), tokenUser);
        } else if (userSiteDO.getStatus() == OFF_JOB.intValue()) {
            // 恢复在职
            UserSiteUpdateDTO userSiteUpdateDTO = userSiteDO.to(UserSiteUpdateDTO.class);
            userSiteUpdateDTO.setStatus(ON_JOB.intValue());
            userSiteService.update(userSiteUpdateDTO, tokenUser);
        }
        //更新用户的用户名
        UserUpdateDTO userUpdateDTO = new UserUpdateDTO();
        userUpdateDTO.setId(existUser.getId());
        userUpdateDTO.setName(addUserDTO.getName());
        userService.update(userUpdateDTO, tokenUser);
        existUser.setName(addUserDTO.getName());
        return existUser.to(UserVO.class);
    }


    @Override
    public Integer updateUserPassword(String userId, String password, TokenUser tokenUser) {
        UserDO userDO = this.selectUserById(userId);
        UserUpdateDTO userUpdateDTO = userDO.to(UserUpdateDTO.class);
        userUpdateDTO.setPassword(password);
        return userService.update(userUpdateDTO, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void updateUserRole(UpdateUserRoleDTO updateUserRoleDTO, TokenUser tokenUser) {
//        ParamException.isFalse(tokenUser.getUserId().equals(updateUserRoleDTO.getUserId()), "不能修改自己的权限，请联系其他管理员");
        HrRoleVO hrRoleVO = hrRoleService.selectById(updateUserRoleDTO.getHrRoleId(), tokenUser.getSiteId());
        ParamException.notNull(hrRoleVO, "人力角色信息有误，请查证后再试");
        String[] split = hrRoleVO.getRoleIds().split(",");
        List<RoleDO> roleDOList = permissionProviderService.selectRoleByIds(Arrays.stream(split)
                .map(Long::parseLong).collect(Collectors.toList()), tokenUser.getSiteId());
        Long roleId = null;
        Long subjectId = null;
        for (RoleDO roleDO : roleDOList) {
            // 操作端角色
            if (COMPANY_SUBJECT_TYPE.equals(roleDO.getSubjectType())) {
                roleId = roleDO.getId();
            }
            // 管理端角色
            if (HR_SUBJECT_TYPE.equals(roleDO.getSubjectType())) {
                subjectId = roleDO.getId();
            }
        }
        ParamException.notNull(roleId, "操作端角色信息有误，请查证后再试");
        ParamException.notNull(subjectId, "管理端角色信息有误，请查证后再试");
        updateUserRoleDTO.setRoleId(roleId);
        // 先删除就得角色权限 再创建新的角色
        updateRole(updateUserRoleDTO.getRoleId(), updateUserRoleDTO.getUserId(), tokenUser);
        // 添加用户在某分公司下有权限的用工单位
        userRoleCompanyService.add(updateUserRoleDTO.getUserId(), updateUserRoleDTO.getRoleId()
                , updateUserRoleDTO.getIsAllChildCompany(), updateUserRoleDTO.getChildCompanyIdList()
                , updateUserRoleDTO.getEmployerIdList(), tokenUser);

        // 管理端角色创建
        RoleMemberAddDTO roleMemberAddDTO = new RoleMemberAddDTO();
        roleMemberAddDTO.setMemberId(updateUserRoleDTO.getUserId());
        roleMemberAddDTO.setRoleId(subjectId);
        roleMemberAddDTO.setSubjectId("0");
        roleMemberAddDTO.setSubjectType(HR_SUBJECT_TYPE);
        roleMemberAddDTO.setType("U");
        permissionProviderService.deleteRoleMember(updateUserRoleDTO.getUserId(), null, HR_SUBJECT_TYPE, null, tokenUser.getSiteId());
        permissionProviderService.addRoleMemberBatch(Collections.singletonList(roleMemberAddDTO), tokenUser);

        // 用户只读属性修改
        if (!ObjectUtils.isEmpty(updateUserRoleDTO.getIsReadOnly())) {
            UserUpdateDTO updateUserDTO = new UserUpdateDTO();
            updateUserDTO.setId(updateUserRoleDTO.getUserId());
            updateUserDTO.setIsReadOnly(updateUserRoleDTO.getIsReadOnly());
            userService.update(updateUserDTO, tokenUser);
        }
        List<String> employerIdList = updateUserRoleDTO.getEmployerIdList();
        if (updateUserRoleDTO.getIsAllChildCompany() != null && updateUserRoleDTO.getIsAllChildCompany()) {
            List<CompanyDO> siteCompanyList = companyService.selectBySiteId(tokenUser.getSiteId());
            List<String> siteCompanyIdList = siteCompanyList.stream().map(CompanyDO::getId).collect(Collectors.toList());
            employerIdList.addAll(siteCompanyIdList);
        }
        saveUserUpdateNotice(hrRoleVO, updateUserRoleDTO.getChildCompanyIdList(), employerIdList,
                updateUserRoleDTO.getUserId(), tokenUser);
    }

    /**
     * 先删除就得角色权限 再创建新的角色
     *
     * @param roleId    用户的角色
     * @param userId    用户id
     * @param tokenUser 当前用户
     */
    private void updateRole(Long roleId, String userId, TokenUser tokenUser) {
        // 新建角色 已经有的角色删除
        permissionProviderService.deleteRoleMember(userId, null, COMPANY_SUBJECT_TYPE, null, tokenUser.getSiteId());
        //修改为某角色，添加角色成员
        if (StrKit.isNotEmpty(roleId)) {
            permissionProviderService.addRoleMember(userId, roleId, COMPANY_SUBJECT_TYPE, "0", tokenUser);
        }
    }

    @Override
    public List<HrUserVO> queryUserList(UserQuery userQuery, String groupId, String siteId) {
        TokenUser tokenUser = UserContext.getUser();
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }
        List<UserDO> userList = userSiteMapperService.selectByIdList(userQuery, memberIdList, siteId);
        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        // 排除渠道用户
        List<ChannelListVO> channelListVOList = channelService.select(new ChannelQuery(), tokenUser.getSiteId());
        // 渠道角色
        List<RoleDO> roleDOList = roleService.selectByName("渠道", COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        List<Long> roleIds = roleDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        // 渠道用户
        List<String> channelUserIds = channelListVOList.parallelStream()
                .map(ChannelListVO::getAdminUserId).collect(Collectors.toList());
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));
        // 用户拥有的权限
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByUserIds(new ArrayList<>(userMap.keySet()), siteId);
        // 用户Id-有权限的用工单位List
        Map<String, List<UserRoleCompanyDO>> userIdMap = userRoleCompanyDOList.parallelStream()
                .collect(Collectors.groupingBy(UserRoleCompanyDO::getUserId));
        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 在渠道表 且 角色为渠道 过滤
            if (channelUserIds.contains(roleMemberListVO.getMemberId()) && roleIds.contains(roleMemberListVO.getRoleId())) {
                return null;
            }
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            List<UserRoleCompanyDO> roleCompanyDOList = userIdMap.get(hrUserVO.getId());
            // 拥有权限是所有用工单位分组或指定用工单位分组
            if (StringUtils.isNotEmpty(groupId)) {
                // 没有权限 直接过滤
                if (CollectionUtils.isEmpty(roleCompanyDOList)) {
                    return null;
                }
                boolean anyMatch = roleCompanyDOList.parallelStream().anyMatch(userRoleCompanyDO -> (userRoleCompanyDO
                        .getIsAllChildCompany() || groupId.equals(userRoleCompanyDO.getChildCompanyId())));
                if (!anyMatch) {
                    return null;
                }
            }
            // 没有用工单位 显示：无
            if (CollectionUtils.isEmpty(roleCompanyDOList)) {
                hrUserVO.setCompanyName("无");
                hrUserVO.setIsAllEmployer(false);
                hrUserVO.setCompanyIdList(new ArrayList<>());
                return hrUserVO;
            }
            boolean isAllChildCompany = roleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany);
            if (isAllChildCompany) {
                hrUserVO.setCompanyName(permissionProviderService.getSiteName(siteId));
                // 站点下用工单位
                List<CompanyDO> companyDOList = companyService.selectBySiteId(siteId);
                List<String> companyNames = companyDOList.parallelStream().map(CompanyDO::getName).collect(Collectors.toList());
                // 站点下用工单位分组
                List<ChildCompanyDO> childCompanyDOList = childCompanyService.selectBySiteId(siteId);
                List<String> childCompanyNames = childCompanyDOList.parallelStream().map(ChildCompanyDO::getName).collect(Collectors.toList());
                companyNames.addAll(childCompanyNames);
                hrUserVO.setCompanyAllName(companyNames.parallelStream().collect(Collectors.joining(",")));
            } else {
                Set<String> companyAllName = new HashSet<>();
                for (UserRoleCompanyDO userRoleCompanyDO : roleCompanyDOList) {
                    if (userRoleCompanyDO.getIsAllEmployer()) {
                        // 用工单位分组
                        ChildCompanyVO childCompanyVO = childCompanyService.selectById(userRoleCompanyDO.getChildCompanyId(), siteId);
                        if (childCompanyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(childCompanyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(childCompanyVO.getName());
                        }
                    } else {
                        // 用工单位
                        CompanyVO companyVO = companyService.selectBaseCompanyById(userRoleCompanyDO.getEmployerId(), tokenUser.getSiteId());
                        if (companyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(companyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(companyVO.getName());
                        }
                    }
                }
                // 拥有的分组
                List<String> childCompanyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getChildCompanyId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                List<String> companyIdList = groupCompanyService.selectCompanyIdListByGroupIds(childCompanyIds, siteId);
                // 拥有的公司
                List<String> companyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getEmployerId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                companyIdList.addAll(companyIds);
                hrUserVO.setCompanyIdList(companyIdList);
                hrUserVO.setCompanyAllName(companyAllName.parallelStream().collect(Collectors.joining(",")));
            }
            hrUserVO.setIsAllEmployer(isAllChildCompany);
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public List<HrUserVO> queryUserList(HrUserQuery hrUserQuery, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            roleMemberQuery.setRoleId(hrUserQuery.getRoleId());
        }
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }
        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);
        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        // 排除渠道用户
        List<ChannelListVO> channelListVOList = channelService.select(new ChannelQuery(), tokenUser.getSiteId());
        // 渠道角色
        List<RoleDO> roleDOList = roleService.selectByName("渠道", COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        List<Long> roleIds = roleDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        // 渠道用户
        List<String> channelUserIds = channelListVOList.parallelStream()
                .map(ChannelListVO::getAdminUserId).collect(Collectors.toList());
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));
        // 用户拥有的权限
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByUserIds(new ArrayList<>(userMap.keySet()), siteId);
        // 用户Id-有权限的用工单位List
        Map<String, List<UserRoleCompanyDO>> userIdMap = userRoleCompanyDOList.parallelStream()
                .collect(Collectors.groupingBy(UserRoleCompanyDO::getUserId));
        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 在渠道表 且 角色为渠道 过滤
            if (channelUserIds.contains(roleMemberListVO.getMemberId()) && roleIds.contains(roleMemberListVO.getRoleId())) {
                return null;
            }
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            List<UserRoleCompanyDO> roleCompanyDOList = userIdMap.get(hrUserVO.getId());
            // 没有用工单位 显示：无
            if (CollectionUtils.isEmpty(roleCompanyDOList)) {
                hrUserVO.setCompanyName("无");
                hrUserVO.setIsAllEmployer(false);
                hrUserVO.setCompanyIdList(new ArrayList<>());
                return hrUserVO;
            }
            boolean isAllChildCompany = roleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany);
            if (isAllChildCompany) {
                hrUserVO.setCompanyName(permissionProviderService.getSiteName(siteId));
                // 站点下用工单位
                List<CompanyDO> companyDOList = companyService.selectBySiteId(siteId);
                List<String> companyNames = companyDOList.parallelStream().map(CompanyDO::getName).collect(Collectors.toList());
                // 站点下用工单位分组
                List<ChildCompanyDO> childCompanyDOList = childCompanyService.selectBySiteId(siteId);
                List<String> childCompanyNames = childCompanyDOList.parallelStream().map(ChildCompanyDO::getName).collect(Collectors.toList());
                companyNames.addAll(childCompanyNames);
                hrUserVO.setCompanyAllName(companyNames.parallelStream().collect(Collectors.joining(",")));
            } else {
                Set<String> companyAllName = new HashSet<>();
                for (UserRoleCompanyDO userRoleCompanyDO : roleCompanyDOList) {
                    if (userRoleCompanyDO.getIsAllEmployer()) {
                        // 用工单位分组
                        ChildCompanyVO childCompanyVO = childCompanyService.selectById(userRoleCompanyDO.getChildCompanyId(), siteId);
                        if (childCompanyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(childCompanyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(childCompanyVO.getName());
                        }
                    } else {
                        // 用工单位
                        CompanyVO companyVO = companyService.selectBaseCompanyById(userRoleCompanyDO.getEmployerId(), tokenUser.getSiteId());
                        if (companyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(companyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(companyVO.getName());
                        }
                    }
                }
                // 拥有的分组
                List<String> childCompanyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getChildCompanyId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                List<String> companyIdList = groupCompanyService.selectCompanyIdListByGroupIds(childCompanyIds, siteId);
                // 拥有的公司
                List<String> companyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getEmployerId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                companyIdList.addAll(companyIds);
                hrUserVO.setCompanyIdList(companyIdList);
                hrUserVO.setCompanyAllName(companyAllName.parallelStream().collect(Collectors.joining(",")));
            }
            hrUserVO.setIsAllEmployer(isAllChildCompany);
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public List<HrUserVO> queryUserListLessToMe(HrUserQuery hrUserQuery, String subjectId, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            roleMemberQuery.setRoleId(hrUserQuery.getRoleId());
        }
        if (StringUtils.isNotEmpty(subjectId)) {
            roleMemberQuery.setSubjectId(subjectId);
        }
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        //校验HR 角色
        if (StringUtils.isNotBlank(hrUserQuery.getCode())) {
            List<String> roleIds = hrRoleService.selectByCode(hrUserQuery.getCode(), tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(roleIds)) {
                roleMemberList = roleMemberList.stream().
                        filter(roleMemberListVO -> roleIds.contains(String.valueOf(roleMemberListVO.getRoleId())))
                        .collect(Collectors.toList());
            }
        }
        String roleCodeStr = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.FILTER_ROLE_CODE, siteId);
        if(!StringUtils.isEmpty(roleCodeStr)){
            String[] roleCodeArray = roleCodeStr.split(",");
            List<String> roleCodeList = Arrays.asList(roleCodeArray);
            List<String> roleIds = hrRoleService.selectByCodeList(roleCodeList, tokenUser.getSiteId());
            if(!CollectionUtils.isEmpty(roleIds)){
                roleMemberList = roleMemberList.stream().
                        filter(roleMemberListVO -> !roleIds.contains(String.valueOf(roleMemberListVO.getRoleId())))
                        .collect(Collectors.toList());
            }
        }
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }

        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);

        // 获取所有成员用户对象 权限小于自己
        userList = selectLessToMe(userList, tokenUser);

        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        // 排除渠道用户
        List<ChannelListVO> channelListVOList = channelService.select(new ChannelQuery(), tokenUser.getSiteId());
        // 渠道角色
        List<RoleDO> roleDOList = roleService.selectByName("渠道", COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        List<Long> roleIds = roleDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        // 渠道用户
        List<String> channelUserIds = channelListVOList.parallelStream()
                .map(ChannelListVO::getAdminUserId).collect(Collectors.toList());
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));
        // 用户拥有的权限
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByUserIds(new ArrayList<>(userMap.keySet()), siteId);
        // 用户Id-有权限的用工单位List
        Map<String, List<UserRoleCompanyDO>> userIdMap = userRoleCompanyDOList.parallelStream()
                .collect(Collectors.groupingBy(UserRoleCompanyDO::getUserId));
        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 在渠道表 且 角色为渠道 过滤
            if (channelUserIds.contains(roleMemberListVO.getMemberId()) && roleIds.contains(roleMemberListVO.getRoleId())) {
                return null;
            }
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            List<UserRoleCompanyDO> roleCompanyDOList = userIdMap.get(hrUserVO.getId());
            // 没有用工单位 显示：无
            if (CollectionUtils.isEmpty(roleCompanyDOList)) {
                hrUserVO.setCompanyName("无");
                hrUserVO.setIsAllEmployer(false);
                hrUserVO.setCompanyIdList(new ArrayList<>());
                return hrUserVO;
            }
            boolean isAllChildCompany = roleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany);
            if (isAllChildCompany) {
                hrUserVO.setCompanyName(permissionProviderService.getSiteName(siteId));
                // 站点下用工单位
                List<CompanyDO> companyDOList = companyService.selectBySiteId(siteId);
                List<String> companyNames = companyDOList.parallelStream().map(CompanyDO::getName).collect(Collectors.toList());
                // 站点下用工单位分组
                List<ChildCompanyDO> childCompanyDOList = childCompanyService.selectBySiteId(siteId);
                List<String> childCompanyNames = childCompanyDOList.parallelStream().map(ChildCompanyDO::getName).collect(Collectors.toList());
                companyNames.addAll(childCompanyNames);
                hrUserVO.setCompanyAllName(companyNames.parallelStream().collect(Collectors.joining(",")));
            } else {
                Set<String> companyAllName = new HashSet<>();
                for (UserRoleCompanyDO userRoleCompanyDO : roleCompanyDOList) {
                    if (userRoleCompanyDO.getIsAllEmployer()) {
                        // 用工单位分组
                        ChildCompanyVO childCompanyVO = childCompanyService.selectById(userRoleCompanyDO.getChildCompanyId(), siteId);
                        if (childCompanyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(childCompanyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(childCompanyVO.getName());
                        }
                    } else {
                        // 用工单位
                        CompanyVO companyVO = companyService.selectBaseCompanyById(userRoleCompanyDO.getEmployerId(), tokenUser.getSiteId());
                        if (companyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(companyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(companyVO.getName());
                        }
                    }
                }
                // 拥有的分组
                List<String> childCompanyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getChildCompanyId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                List<String> companyIdList = groupCompanyService.selectCompanyIdListByGroupIds(childCompanyIds, siteId);
                // 拥有的公司
                List<String> companyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getEmployerId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                companyIdList.addAll(companyIds);
                hrUserVO.setCompanyIdList(companyIdList);
                if (CollectionUtils.isEmpty(companyAllName)) {
                    hrUserVO.setCompanyAllName("无");
                } else {
                    hrUserVO.setCompanyAllName(companyAllName.parallelStream().collect(Collectors.joining(",")));
                }
            }
            hrUserVO.setIsAllEmployer(isAllChildCompany);
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public Page<HrUserVO> pageUserListLessToMe(HrUserQuery hrUserQuery, TokenUser tokenUser) {
        List<String> roleIdList = new ArrayList<>();
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            HrRoleVO hrRole = hrRoleService.selectById(hrUserQuery.getRoleId(), tokenUser.getSiteId());
            String hrRoleIds = hrRole.getRoleIds();
            roleIdList = Arrays.asList(hrRoleIds.split(","));
        }
        String siteId = tokenUser.getSiteId();
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);

        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new Page<>(hrUserQuery.getPageSize(), hrUserQuery.getPageNo());
        }
        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);
        // 获取所有成员用户对象 权限小于自己
        userList = selectLessToMe(userList, tokenUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new Page<>(hrUserQuery.getPageSize(), hrUserQuery.getPageNo());
        }
        // 排除渠道用户
        List<ChannelListVO> channelListVOList = channelService.select(new ChannelQuery(), tokenUser.getSiteId());
        // 渠道角色
        List<RoleDO> roleDOList = roleService.selectByName("渠道", COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        List<Long> roleIds = roleDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        // 渠道用户
        List<String> channelUserIds = channelListVOList.parallelStream()
                .map(ChannelListVO::getAdminUserId).collect(Collectors.toList());
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));
        List<HrUserVO> returnList = roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 在渠道表 且 角色为渠道 过滤
            if (channelUserIds.contains(roleMemberListVO.getMemberId()) && roleIds.contains(roleMemberListVO.getRoleId())) {
                return null;
            }
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleIdList)) {
            List<String> finalRoleIdList = roleIdList;
            returnList = returnList.stream()
                    .filter(user -> finalRoleIdList.contains(user.getRoleId() + "")).collect(Collectors.toList());
        }
        return PageKit.startPage(returnList, hrUserQuery.getPageNo(), hrUserQuery.getPageSize());
    }

    @Override
    public void addSuperAdmin(List<HrUserVO> result, TokenUser tokenUser) {
        //获取首位超级管理员的user
        String userId = permissionProviderService.findMemberIdBySubject(PermissionConstants.ROLE_MEMBER_TYPE_USER,
                SYSTEM_SUBJECT_TYPE, HR_DEFAULT_SUBJECT_ID, tokenUser.getSiteId());
        UserDO userDO = selectUserById(userId);
        HrUserVO superAdmin = userDO.to(HrUserVO.class);
        List<String> userIdList = result.stream().map(HrUserVO::getId).collect(Collectors.toList());
        if (!userIdList.contains(userId)) {
            result.add(superAdmin);
        }
    }

    /**
     * 查询比当前用户小的用户
     *
     * @param userList  符合条件的用户
     * @param tokenUser 登录用户
     * @return 用户列表
     */
    private List<UserDO> selectLessToMe(List<UserDO> userList, TokenUser tokenUser) {

        List<UserRoleCompanyDO> userRoleCompanyDOList
                = userRoleCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        // 仅仅是管理员 可以查看所有人
        if (CollectionUtils.isEmpty(userRoleCompanyDOList) && hrPermissionService.isAdmin(tokenUser.getUserId(), tokenUser.getSiteId())) {
            return userList;
        }
        // 有总公司权限 可以查看所有人
        if (userRoleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany)) {
            return userList;
        }
        List<String> groupIds = new ArrayList<>();
        List<String> companyIds = new ArrayList<>();
        for (UserRoleCompanyDO userRoleCompanyDO : userRoleCompanyDOList) {
            if (userRoleCompanyDO.getIsAllEmployer()) {
                groupIds.add(userRoleCompanyDO.getChildCompanyId());
            } else {
                companyIds.add(userRoleCompanyDO.getEmployerId());
            }
        }
        // 登录员工没有任何权限 返回空数组
        if (CollectionUtils.isEmpty(groupIds) && CollectionUtils.isEmpty(companyIds)) {
            userList = new ArrayList<>();
        }

        List<String> allGroupIds = childCompanyService.groupTreeIds(groupIds, tokenUser.getSiteId());
        List<String> allCompanyIds = groupCompanyService.selectCompanyIdListByGroupIds(allGroupIds, tokenUser.getSiteId());
        companyIds.addAll(allCompanyIds);

        // 非指定权限的员工
        List<String> excludeUserIds = userRoleCompanyService
                .selectNotInChildCompanyIdsAndEmployerIds(allGroupIds, companyIds, tokenUser.getSiteId());
        return userList.parallelStream().filter(userDO -> !excludeUserIds.contains(userDO.getId())).collect(Collectors.toList());
    }

    /**
     * 根据用户角色获取人力用户
     *
     * @param roleMemberListVO 角色成员
     * @param userMap          用户集合
     * @param siteId
     * @return 人力用户
     */
    private HrUserVO getHrUserByRoleMember(RoleMemberListVO roleMemberListVO, Map<String, UserDO> userMap, String siteId) {
        UserDO userDO = userMap.get(roleMemberListVO.getMemberId());
        if (Objects.isNull(userDO)) {
            return null;
        }
        HrUserVO hrUserVO = new HrUserVO();
        hrUserVO.setId(roleMemberListVO.getMemberId());
        hrUserVO.setName(userDO.getName());
        hrUserVO.setPhone(userDO.getPhone());
        hrUserVO.setStatus(userDO.getStatus());
        hrUserVO.setPinyin(userDO.getPinyin());
        hrUserVO.setAvatar(userDO.getAvatar());
        hrUserVO.setEmail(userDO.getEmail());
        hrUserVO.setIsReadOnly(userDO.getIsReadOnly());
        hrUserVO.setRoleId(roleMemberListVO.getRoleId());
        HrRoleDO hrRoleDO = hrRoleService.selectByRoleId(roleMemberListVO.getRoleId(), siteId);
        if (hrRoleDO != null) {
            hrUserVO.setHrRoleId(hrRoleDO.getId());
        }
        hrUserVO.setRoleName(roleMemberListVO.getRoleName());
        return hrUserVO;
    }

    /**
     * 获取分公司名称
     *
     * @param childCompanyId 分公司id
     * @param siteId         站点
     * @return 分公司名称
     */
    @Override
    public String getChildCompanyName(String childCompanyId, String siteId) {
        if ("supreme".equals(childCompanyId)) {
            String siteName = permissionProviderService.getSiteName(siteId);
            return StringUtils.isEmpty(siteName) ? "总公司" : "(总) " + siteName;
        } else {
            ChildCompanyDO childCompanyDO = childCompanyService.selectDOById(childCompanyId, siteId);
            if (Objects.nonNull(childCompanyDO)) {
                return "(分) " + childCompanyDO.getName();
            } else {
                return "";
            }
        }
    }

    @Override
    public List<String> selectUserIdHasRoleInCompany(String companyId, TokenUser tokenUser) {
        List<HrUserVO> hrUserVOList = selectUserHasRoleInCompany(companyId, tokenUser);
        if (CollectionUtils.isEmpty(hrUserVOList)) {
            return new ArrayList<>();
        }
        return hrUserVOList.parallelStream().map(HrUserVO::getId).collect(Collectors.toList());
    }

    @Override
    public List<HrUserVO> listUserHasRoleInCompany(UserQuery userQuery, String companyId, TokenUser tokenUser) {
        //获取所有成员用户对象
        HrUserQuery hrUserQuery = userQuery.to(HrUserQuery.class);
        String siteId = tokenUser.getSiteId();
        // 指定用工单位是否在分组下
        List<GroupCompanyDO> groupCompanyDOList = groupCompanyService
                .selectByCompanyIds(Collections.singletonList(companyId), tokenUser.getSiteId());
        // 用工单位所在分组
        List<String> groupIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupCompanyDOList)) {
            // 在分组
            groupIds = groupCompanyDOList.parallelStream().map(GroupCompanyDO::getGroupId).distinct().collect(Collectors.toList());
        }
        // 用户拥有权限的用工单位
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByCompanyIdOrGroupIds(groupIds, companyId, siteId);
        if (CollectionUtils.isEmpty(userRoleCompanyDOList)) {
            return new ArrayList<>();
        }
        List<String> userIds = userRoleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getUserId).collect(Collectors.toList());
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            roleMemberQuery.setRoleId(hrUserQuery.getRoleId());
        }
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        //
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).filter(userIds::contains)
                .distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }
        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);
        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));

        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public List<HrUserVO> listUserHasRoleInSite(UserQuery userQuery, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();

        //获取所有成员用户对象
        HrUserQuery hrUserQuery = userQuery.to(HrUserQuery.class);
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectBySiteId(tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(userRoleCompanyDOList)) {
            return new ArrayList<>();
        }
        List<String> userIds = userRoleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getUserId).collect(Collectors.toList());
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            roleMemberQuery.setRoleId(hrUserQuery.getRoleId());
        }
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        //
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).filter(userIds::contains)
                .distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }
        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);
        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));

        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public Page<HrUserVO> pageUserHasRoleInCompany(UserQuery userQuery, String companyId, TokenUser tokenUser) {

        List<HrUserVO> hrUserVOList = listUserHasRoleInCompany(userQuery, companyId, tokenUser);

        return PageKit.startPage(hrUserVOList, userQuery.getPageNo(), userQuery.getPageSize());
    }

    @Override
    public Page<HrUserVO> pageUserHasRoleInSite(UserQuery userQuery, TokenUser tokenUser) {

        List<HrUserVO> hrUserVOList = listUserHasRoleInSite(userQuery, tokenUser);

        return PageKit.startPage(hrUserVOList, userQuery.getPageNo(), userQuery.getPageSize());
    }

    @Override
    public List<HrUserVO> selectUserHasRoleInCompany(String companyId, TokenUser tokenUser) {
        UserQuery userQuery = new UserQuery();

        return listUserHasRoleInCompany(userQuery, companyId, tokenUser);
    }

    @Override
    public List<HrUserVO> listEmpAndRoleUserInCompany(UserQuery userQuery, String companyId, TokenUser tokenUser) {
        // 有权限的 用户
        List<HrUserVO> hrUserList = listUserHasRoleInCompany(userQuery, companyId, tokenUser);
        List<String> userIdList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(hrUserList)) {
            userIdList = hrUserList.parallelStream().map(HrUserVO::getId).collect(Collectors.toList());
        } else {
            hrUserList = new ArrayList<>();
        }
        // 获取公司下员工对应的用户
        List<String> empUserIdList = empInfoService.listEmpUserIdByCompany(companyId, tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(empUserIdList)) {
            // 移除已经查询过的
            empUserIdList.removeAll(userIdList);
            if (!CollectionUtils.isEmpty(empUserIdList)) {
                List<UserDO> empUserList = userSiteMapperService.selectByIdList(userQuery, empUserIdList, tokenUser.getSiteId());
                if (!CollectionUtils.isEmpty(empUserList)) {
                    List<HrUserVO> empHrUserList = empUserList.stream()
                            .map(empUser -> empUser.to(HrUserVO.class))
                            .collect(Collectors.toList());
                    hrUserList.addAll(empHrUserList);
                }
            }
        }
        return hrUserList;
    }

    @Override
    public Page<HrUserVO> pageEmpAndRoleUserInCompany(UserQuery userQuery, String companyId, TokenUser tokenUser) {
        List<HrUserVO> hrUserList = listEmpAndRoleUserInCompany(userQuery, companyId, tokenUser);
        return PageKit.startPage(hrUserList, userQuery.getPageNo(), userQuery.getPageSize());
    }

    @Override
    public Page<HrUserVO> querySimpleUserPage(UserQuery userQuery, String siteId) {
        Page<UserListVO> userPage = userSiteMapperService.selectPage(userQuery, siteId);
        return userPage.to(HrUserVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void dimissionUser(String[] userIds, TokenUser tokenUser) {
        List<String> idsList = Arrays.asList(userIds);
        idsList.parallelStream().forEach(userId -> userSiteService.dimissionUser(userId, tokenUser));
    }

    @Override
    public void recoverUser(String userId, TokenUser tokenUser) {
        userSiteService.recoverUser(userId, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteUser(String[] userIds, TokenUser tokenUser) {
        //删除用户站点
//        userSiteService.deleteByUserIds(TO_B, tokenUser, userIds);
        //同时删除角色
        permissionProviderService.deleteUserRoleMember(tokenUser, userIds);
        // 删除员工有权限的用工单位
        userRoleCompanyService.deleteByUserIdAndSiteId(Arrays.asList(userIds), tokenUser.getSiteId());
        // 删除回款计划中间表
        empSocBackResponsibleService.deleteByUserId(Arrays.asList(userIds));
    }

    @Override
    public UserDO selectUserById(String userId) {
        return userService.selectDOById(userId);
    }

    @Override
    public List<UserDO> selectUserByIds(List<String> userIds) {
        return userService.selectByIds(userIds);
    }

    @Override
    public UserDO selectByPhone(String phone) {
        return userService.selectByPhone(phone);
    }


    @Override
    @Transactional(value = UserConstants.TX, rollbackFor = Exception.class)
    public UserVO onlySaveUser(UserAddDTO userAddDTO) {
        TokenUser defaultTokenUser = new TokenUser();
        defaultTokenUser.setUserId("system");
        defaultTokenUser.setSiteId("default");
        //注册用户
        return saveUserAndSite(userAddDTO, defaultTokenUser);
    }

    @Override
    @Transactional(value = UserConstants.TX, rollbackFor = Exception.class)
    public UserVO saveUserAndSite(UserAddDTO userAddDTO, TokenUser tokenUser) {
        //注册用户
        return userSiteMapperService.save(userAddDTO, tokenUser);
    }

    @Override
    public UserVO registerAccount(String name, String phone, TokenUser tokenUser, String companyId) {
        ParamException.notNull(phone, "手机号不能为空");
        UserVO userVO;
        //验证手机号是否已注册过用户
        UserDO userDO = this.selectByPhone(phone);
        if (Objects.isNull(userDO)) {
            //用户不存在
            UserAddDTO userAddDTO = new UserAddDTO();
            userAddDTO.setPhone(phone);
            userAddDTO.setName(StrKit.isEmpty(name) ? phone : name);
            userVO = saveUserAndSite(userAddDTO, tokenUser);
        } else {
            UserSiteDO userSite = userSiteService.selectByUserIdAndSiteId(userDO.getId(), tokenUser.getSiteId(), TO_B);
            //保存userSite表
            if (Objects.isNull(userSite)) {
                this.saveUserSite(userDO.getId(), tokenUser);
            } else if (!userSite.getStatus().equals(UserConstants.ON_JOB.intValue())) {
                // 非在职状态
                recoverUser(userSite.getUserId(), tokenUser);
            }
            //用户已存在
            userVO = userDO.to(UserVO.class);
        }

        //查询员工unionId
        EmpInfoVO empInfoVO = empInfoService.selectByPhone(companyId, phone, tokenUser.getSiteId());
        if (Objects.nonNull(empInfoVO)) {
            String unionId = empInfoVO.getUnionId();

            //员工绑定userId
            empInfoService.updateEmpUserIdById(empInfoVO.getId(), userVO.getId());

            // 如果已经实名认证过了，直接认证
            if (nameVerifiedService.isUserVerified(userVO.getId(), tokenUser.getSiteId())) {
                EmpInfoDO empInfoUp = new EmpInfoDO();
                empInfoUp.setId(empInfoVO.getId());
                empInfoUp.setVerified(Boolean.TRUE);
                empInfoService.updateByIdSelective(empInfoUp, tokenUser.getSiteId(), tokenUser.getUserId());
            }

            if (StrKit.isNotEmpty(unionId)) {
                //绑定微信
                thirdInfoService.bindWechat(userVO.getId(), unionId);
            }
        }

        return userVO;
    }

    /**
     * 修改用户userSite表状态
     *
     * @param userSiteId 表主键
     * @param tokenUser  当前用户
     */
    private void updateUserSiteStatus(Long userSiteId, TokenUser tokenUser) {
        UserSiteUpdateDTO update = new UserSiteUpdateDTO();
        update.setId(userSiteId);
        update.setStatus(UserConstants.ON_JOB.intValue());

        userSiteService.update(update, tokenUser);
    }

    @Override
    public ThirdInfoDO selectThirdInfoByUserId(String appId, String userId) {
        return thirdInfoService.selectByUserIdAndAppId(userId, appId);
    }


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void updateUserPhone(String userId, String oldPhone, String newPhone, TokenUser tokenUser) {
        // 新手机号已注册 查询站点下有无员工 无员工 则转移员工到新用户下
        List<EmpInfoDO> oldEmpInfoList = empInfoService.selectByPhoneNotSiteId(newPhone);
        if (!CollectionUtils.isEmpty(oldEmpInfoList)) {
            List<String> companyIds = oldEmpInfoList.parallelStream().map(EmpInfoDO::getCompanyId).distinct().collect(Collectors.toList());
            List<CompanyDO> companyDOList = companyService.selectByIdsNotSiteId(companyIds);
            throw new ParamException("该手机号已在用工单位：" + companyDOList.parallelStream()
                    .map(CompanyDO::getName).collect(Collectors.joining(",", "[", "]")) + " 中创建员工，请删除后再尝试");
        }

        UserDO userDO = userService.selectDOById(userId);
        ParamException.notNull(userDO, "用户不存在");
        // 修改前的员工信息
        List<EmpInfoDO> empInfoDOList = empInfoService.selectByPhoneNotSiteId(oldPhone);
        UserDO existUser = this.selectByPhone(newPhone);
        TokenUser defaultUser = new TokenUser();
        defaultUser.setSiteId("default");
        defaultUser.setUserId("system");
        // 新手机号没有用户信息 直接更换原用户的手机号
        if (existUser != null) {
            userService.logicalDeleteByIds(existUser.getSiteId(), tokenUser.getUserId(), existUser.getId());
        }
        UserDO updateDO = new UserDO();
        updateDO.setId(userId);
        updateDO.setPhone(newPhone);
        // 更新用户表手机号，原手机号缓存会删除
        userService.updateSelective(updateDO, tokenUser.getSiteId(), tokenUser.getUserId());

        //判断是不是销售、渠道、同步更新
        saleUserService.updatePhone(userId, newPhone);

        channelService.updatePhone(userId, newPhone);


        for (EmpInfoDO infoDO : empInfoDOList) {
            // 保存更换手机号的记录
            EmpModifyPhoneAddDTO empModifyPhoneAddDTO = new EmpModifyPhoneAddDTO();
            empModifyPhoneAddDTO.setEmpId(infoDO.getId());
            empModifyPhoneAddDTO.setOldPhone(oldPhone);
            empModifyPhoneAddDTO.setNewPhone(newPhone);
            empModifyPhoneAddDTO.setOldUserId(userId);
            empModifyPhoneAddDTO.setNewUserId(userId);
            empModifyPhoneAddDTO.setIsUpdateUserId(false);
            empModifyPhoneService.save(empModifyPhoneAddDTO, defaultUser);
        }
    }


    @Override
    public void saveUserSite(String userId, TokenUser tokenUser) {
        UserSiteAddDTO userSiteAddDTO = new UserSiteAddDTO();
        userSiteAddDTO.setUserId(userId);
        userSiteAddDTO.setUserSiteId(tokenUser.getSiteId());
        userSiteAddDTO.setStatus(ON_JOB.intValue());
        userSiteAddDTO.setTerminalType(TO_B);
        userSiteService.save(userSiteAddDTO, tokenUser);
    }

    @Override
    public UnionOpenIdDO getUnionOpenIdDO(String appId, String unionId, String userId) {
        if (StringUtils.isEmpty(appId) && StringUtils.isEmpty(userId)) {
            return null;
        }
        if (StringUtils.isEmpty(unionId)) {
            ThirdInfoDO thirdInfo = selectThirdInfoByUserId(appId, userId);
            if (Objects.nonNull(thirdInfo)) {
                unionId = thirdInfo.getUnionId();
            }
        }
        if (StringUtils.isNotEmpty(unionId)) {
            return unionOpenIdService.selectOpenId(unionId, appId);
        }
        return null;
    }

    @Override
    public Boolean bindWeChatFromOfficialAccount(WeChatBindFromOffAccountDTO weChatBindFromOffAccountDTO) {
        // 根据租户ID和手机号查询员工
        Example example = new Example(EmpInfoDO.class);
        example.and()
                .andEqualTo("phone", weChatBindFromOffAccountDTO.getPhone())
                .andEqualTo("siteId", weChatBindFromOffAccountDTO.getSiteId())
                .andNotEqualTo("status", 4)
                .andEqualTo("valid", true);
        EmpInfoDO empInfoDO = empInfoDAO.selectOneByExample(example);
        if (!Objects.nonNull(empInfoDO)) {
            throw new ParamException("该手机号没有员工信息，请重新输入手机号");
        } else if (StringUtils.isNotBlank(empInfoDO.getUnionId())) {
            if (!weChatBindFromOffAccountDTO.getUnionId().equals(empInfoDO.getUnionId())) {
                throw new ParamException("该手机号已绑定其他微信");
            }
            throw new ParamException("该手机号已绑定过，无需重新绑定");
        }

        // 根据员工userId查询用户信息
        String userId = "";
        if (StringUtils.isBlank(empInfoDO.getUserId())) {
            // 员工未开通用户，执行开通用户
            TokenUser tokenUser = new TokenUser();
            tokenUser.setSiteId(empInfoDO.getSiteId());
            tokenUser.setUserId(empInfoDO.getCreateUserId());
            UserVO userVO = registerAccount(empInfoDO.getName(), empInfoDO.getPhone(), tokenUser, empInfoDO.getCompanyId());
            userId = userVO.getId();
            // 更新员工信息
            empInfoDO.setUserId(userId);
            empInfoService.updateByIdSelective(empInfoDO, empInfoDO.getSiteId(), empInfoDO.getCreateUserId());
        } else {
            UserDO userDO = userService.selectDOById(empInfoDO.getUserId());
            if (!Objects.nonNull(userDO)) {
                throw new ParamException("未找到该手机号员工的用户信息");
            }
            userId = userDO.getId();
        }

        // 验证unionId是否已绑定在其他员工
        Example exampleEmpUnionId = new Example(EmpInfoDO.class);
        exampleEmpUnionId.and()
                .andEqualTo("unionId", weChatBindFromOffAccountDTO.getUnionId())
                .andEqualTo("valid", true)
                .andNotEqualTo("status", 4);
        List<EmpInfoDO> empInfoDOList = empInfoDAO.selectByExample(exampleEmpUnionId);
        if (CollectionUtils.isEmpty(empInfoDOList)) {
            // unionId未绑定在其他员工

        } else {
            // unionId已绑定在其他员工，解绑
            empInfoDOList.forEach(item -> {
                item.setUnionId(null);
                empInfoDAO.updateByPrimaryKey(item);
            });
        }

        // 更新员工unionId
        empInfoDO.setUnionId(weChatBindFromOffAccountDTO.getUnionId());
        empInfoDAO.updateByPrimaryKeySelective(empInfoDO);
        // 获取第三方信息
        Map<String, Object> map = messageHandlerUtil.getUserInfo(weChatBindFromOffAccountDTO.getOpenId(),
                weChatBindFromOffAccountDTO.getSiteId());
        if (map != null) {
            String nickName = map.get("nickname") == null ? "" : map.get("nickname").toString();
            String headImage = map.get("headimgurl") == null ? "" : map.get("headimgurl").toString();
            Integer sex = map.get("sex") == null ? null : Integer.valueOf(map.get("sex").toString());
            String city = map.get("city") == null ? "" : map.get("city").toString();
            String province = map.get("province") == null ? "" : map.get("province").toString();
            String country = map.get("country") == null ? "" : map.get("country").toString();
            // 添加微信第三方信息
            Date now = DateKit.getToday();
            ThirdInfoDO thirdInfoDOTmp = thirdInfoService.selectByUnionId(weChatBindFromOffAccountDTO.getUnionId());
            if (!Objects.nonNull(thirdInfoDOTmp)) {
                ThirdInfoDO thirdInfoDO = new ThirdInfoDO();
                BeanUtils.copyProperties(weChatBindFromOffAccountDTO.getThirdInfoDO(), thirdInfoDO);
                thirdInfoDO.setUnionId(weChatBindFromOffAccountDTO.getUnionId());
                thirdInfoDO.setUserId(userId);

                thirdInfoDO.setHeadImgUrl(headImage);
                thirdInfoDO.setNickName(nickName);
                thirdInfoDO.setSex(sex);
                thirdInfoDO.setCity(city);
                thirdInfoDO.setCountry(country);
                thirdInfoDO.setProvince(province);

                thirdInfoDO.setGmtCreate(now);
                thirdInfoDO.setCreateUserId(userId);
                thirdInfoDO.setGmtModified(now);
                thirdInfoDO.setModifiedUserId(userId);
                thirdInfoDO.setSiteId(weChatBindFromOffAccountDTO.getSiteId());
                thirdInfoDAO.insertSelective(thirdInfoDO);
            } else {
                thirdInfoDOTmp.setUserId(userId);
                thirdInfoDOTmp.setGmtModified(now);
                thirdInfoDAO.updateByPrimaryKeySelective(thirdInfoDOTmp);
            }

        }
        String templateId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_SUBSCRIBE_TEMP_ID,
                weChatBindFromOffAccountDTO.getSiteId());
        // 推送绑定成功模板消息
        WeiXinDTO weiXinDTO = new WeiXinDTO();
        weiXinDTO.setTemplateId(templateId);
        weiXinDTO.setToUser(weChatBindFromOffAccountDTO.getOpenId());
        // 参数
//        String title = "您已成功关注橙事新人";
//        String contentTmp = "您可点此跳转橙事新人小程序";
        // 拼装当前用户
        TokenUser tokenUser = new TokenUser();
        tokenUser.setSiteId("default");
        tokenUser.setUserId("system");

        List<WxTemplateParam> paramList = new ArrayList<>();
        WxTemplateParam param1 = new WxTemplateParam();
        param1.setName("first");
        param1.setValue("您好，账号绑定成功！");
        paramList.add(param1);
        WxTemplateParam param2 = new WxTemplateParam();
        param2.setName("keyword1");
        param2.setValue(empInfoDO.getPhone());
        paramList.add(param2);
        WxTemplateParam param3 = new WxTemplateParam();
        param3.setName("keyword2");
        param3.setValue(DateKit.getDateStr(new Date()));
        paramList.add(param3);
        WxTemplateParam param5 = new WxTemplateParam();
        param5.setName("remark");
        param5.setValue("您可以使用下方菜单体验更多功能");
        paramList.add(param5);

        weiXinDTO.setTemplateParamList(paramList);
        // 跳转小程序
        WxMiNiParam wxMiNiParam = new WxMiNiParam();
        // 小程序appid
        String miniAppid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_SUBSCRIBE_TEMP_ID,
                weChatBindFromOffAccountDTO.getSiteId());
        // 小程序跳转首页
        String path = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_PAGE_PATH,
                weChatBindFromOffAccountDTO.getSiteId());
        wxMiNiParam.setAppid(miniAppid);
        wxMiNiParam.setPagepath(path);
        weiXinDTO.setMiniProgram(wxMiNiParam);
        messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);

        return true;
    }

    @Override
    public void updateAllUserPinyin() {
        List<UserDO> userList = userService.selectDO(new UserQuery());
        userList.parallelStream().forEach(userDO -> {
            UserDO updateUser = new UserDO();
            updateUser.setId(userDO.getId());
            updateUser.setName(userDO.getName());
            userService.updateSelective(userDO, DEFAULT_SITE_ID, "system");
        });
    }

    @Override
    public UnionOpenIdDO getUnionOpenByUserId(String appId, String userId) {
        return getUnionOpenIdDO(appId, "", userId);
    }

    @Override
    public List<String> listChildCompanyByUser(String userId, String siteId) {
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        roleMemberQuery.setMemberId(userId);

        // 获取符合条件的角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        if (!CollectionUtils.isEmpty(roleMemberList)) {
            return roleMemberList.parallelStream()
                    .map(RoleMemberListVO::getSubjectId)
                    .collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public ThirdInfoDO selectByUnionId(String unionId) {
        return thirdInfoService.selectByUnionId(unionId);
    }

    @Override
    public JwtTokenDTO switchToken(String token, String siteId) {
        return tokenService.switchToken(token, siteId);
    }

    @Override
    public UserVO registerUser(String name, String phone) {
        UserVO resultUserVO;
        TokenUser tokenUser = new TokenUser();
        tokenUser.setSiteId("default");
        tokenUser.setUserId("system");
        //验证手机号是否已注册过用户
        UserDO userDO = this.selectByPhone(phone);
        if (Objects.isNull(userDO)) {
            //用户不存在
            UserAddDTO userAddDTO = new UserAddDTO();
            userAddDTO.setPhone(phone);
            userAddDTO.setName(StrKit.isEmpty(name) ? phone : name);
            //注册用户
            resultUserVO = userService.save(userAddDTO, tokenUser);
        } else {
            resultUserVO = userDO.to(UserVO.class);
        }
        return resultUserVO;
    }


    @Override
    public ThirdInfoDO selectUserSettingById(String userId) {
        return thirdInfoService.selectByUserId(userId);
    }

    @Override
    public List<ThirdInfoDO> selectUserSettingByIds(List<String> userIds) {
        return thirdInfoService.selectByUserIds(userIds);
    }


    @Override
    public void unbindWechatByUserId(String userId) {
        thirdInfoService.deleteThirdInfoByUserId(userId);
        // 解绑后清除缓存中用户信息
        String key = CacheKeyKit.getUserInfoKeyByUserId(userId);
        cache.delKey(key);
    }

    @Override
    public UnionOpenIdDO selectByUnionIdAndOpenIdAndAppId(String unionId, String openId, String appId) {
        UnionOpenIdDO unionOpenIdDO = unionOpenIdService.selectByUnionIdAndOpenIdAndAppId(unionId, openId, appId);
        log.info("======查询unionOpenId记录: unionId:{},openId:{},appId:{},unionOpenIdDO:{}",
                unionId, openId, appId, unionOpenIdDO);
        return unionOpenIdDO;
    }

    @Override
    public int deleteByUnionIdAndOpenIdAndAppId(String unionId, String openId, String appId) {
        return unionOpenIdService.deleteByUnionIdAndOpenIdAndAppId(unionId, openId, appId);
    }

    @Override
    public List<UnionOpenIdDO> selectByOpenId(String openId) {
        return unionOpenIdService.selectByOpenId(openId);
    }

    @Override
    public int deleteByOpenId(String openId) {
        return unionOpenIdService.deleteByOpenId(openId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public UserDO updatePhoneByVoucher(String voucher, String phone, String code, TokenUser tokenUser) {

        UserDO userDO = userService.selectDOById(tokenUser.getUserId());
        userService.updatePhoneByVoucher(voucher, phone, code, tokenUser);
        userDO.setPhone(phone);
        return userDO;
    }

    @Override
    public Boolean checkCodeWithUser(String code, String phone, String scene, TokenUser tokenUser) {
        return certificationService.checkCodeWithUser(code, phone, scene, tokenUser);
    }

    @Override
    public SystemConfigVO selectSystemConfigByDomain(String domain) {
        return systemConfigService.selectByDomain(domain);
    }

    @Override
    public List<UserSiteDO> selectUserSiteByUserId(String userId) {
        return userSiteService.selectByUserId(userId);
    }

    @Override
    public int deleteUserSiteByIds(TokenUser tokenUser, Long... userSiteIds) {
        return userSiteService.deleteByIds(tokenUser, userSiteIds);
    }

    @Override
    public PhoneNumberDTO getPhoneNoInfo(WechatXcxLoginDTO wechatXcxLoginDTO, String deviceType) {
        return wechatService.getPhoneInfoByEncrypt(wechatXcxLoginDTO, deviceType);
    }

    @Override
    public Page<LoginLogDO> loginLogPageNotSiteId(LoginLogQuery loginLogQuery) {
        return loginLogService.pageNotSiteId(loginLogQuery);
    }

    @Override
    public List<UserSiteDO> selectByUserId(String userId) {
        return userSiteService.selectByUserId(userId);
    }

    @Override
    public UnionOpenIdDO selectOpenId(String unionId, String appId) {
        return unionOpenIdService.selectOpenId(unionId, appId);
    }

    // 根据userId 查询openid
    @Override
    public String selectOpenIdByUserId(String userId, TokenUser tokenUser) {
        if (StrKit.isEmpty(userId)) {
            return null;
        }
        // 获取spAppid   租户配置了会查询租户的
        String spAppid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.SP_APPID, tokenUser.getSiteId());
        if (StrKit.isEmpty(spAppid)) {
//            throw new ParamException("没有配置 微信批量转账使用的appid");
            log.error("没有配置 微信批量转账使用的appid");
            return null;
        }
        ThirdInfoDO thirdInfoDO = this.selectThirdInfoByUserId(spAppid, userId);
        if (thirdInfoDO == null) {
            return null;
        }
        UnionOpenIdDO unionOpenIdDO = this.selectOpenId(thirdInfoDO.getUnionId(), spAppid);
        if (unionOpenIdDO == null) {
            return null;
        }
        return unionOpenIdDO.getOpenId();
    }

    @Override
    public String selectOpenIdByUserIdAndAppId(String userId, String appId, TokenUser tokenUser) {
        if (StrKit.isEmpty(userId) || StrKit.isEmpty(appId)) {
            return null;
        }
        ThirdInfoDO thirdInfoDO = this.selectThirdInfoByUserId(appId, userId);
        if (thirdInfoDO == null) {
            return null;
        }
        UnionOpenIdDO unionOpenIdDO = this.selectOpenId(thirdInfoDO.getUnionId(), appId);
        if (unionOpenIdDO == null) {
            return null;
        }
        return unionOpenIdDO.getOpenId();
    }

    @Override
    public UserVO selectById(String userId) {
        if (StrKit.isEmpty(userId)) {
            return null;
        }
        return userService.selectById(userId);
    }

    @Override
    public UnionOpenIdDO getUnionOpenIdByUser(String useId, String appId) {
        ThirdInfoDO thirdInfoDO = thirdInfoService.selectByUserIdAndAppId(useId, appId);
        log.info("======第三方信息：{}", thirdInfoDO);
        if (Objects.isNull(thirdInfoDO)) {
            return null;
        }
        String unionId = thirdInfoDO.getUnionId();
        if (StringUtils.isEmpty(unionId)) {
            return null;
        }
        return unionOpenIdService.selectOpenId(unionId, appId);
    }

    @Override
    public List<HrUserVO> queryUserJiaFang(HrUserQuery hrUserQuery, String subjectId, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setSubjectType(COMPANY_SUBJECT_TYPE);
        // 指定角色
        if (hrUserQuery.getRoleId() != null) {
            roleMemberQuery.setRoleId(hrUserQuery.getRoleId());
        }
        if (StringUtils.isNotEmpty(subjectId)) {
            roleMemberQuery.setSubjectId(subjectId);
        }
        //获取所有角色成员
        List<RoleMemberListVO> roleMemberList = permissionProviderService.selectRoleMemberList(roleMemberQuery, siteId);
        //校验HR 角色
        if (StringUtils.isNotBlank(hrUserQuery.getCode())) {
            List<String> roleIds = hrRoleService.selectByCode(hrUserQuery.getCode(), tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(roleIds)) {
                roleMemberList = roleMemberList.stream().
                        filter(roleMemberListVO -> roleIds.contains(String.valueOf(roleMemberListVO.getRoleId())))
                        .collect(Collectors.toList());
            }
        }
        List<String> memberIdList = roleMemberList.stream().map(RoleMemberListVO::getMemberId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(memberIdList)) {
            return new ArrayList<>();
        }

        List<UserDO> userList = userSiteMapperService.selectByIdList(hrUserQuery, memberIdList, siteId);

        // 获取所有成员用户对象 权限小于自己
        userList = selectLessToMe(userList, tokenUser);

        if (CollectionUtils.isEmpty(userList)) {
            return new ArrayList<>();
        }
        // 排除渠道用户
        List<ChannelListVO> channelListVOList = channelService.select(new ChannelQuery(), tokenUser.getSiteId());
        // 渠道角色
        List<RoleDO> roleDOList = roleService.selectByName("渠道", COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        List<Long> roleIds = roleDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        // 渠道用户
        List<String> channelUserIds = channelListVOList.parallelStream()
                .map(ChannelListVO::getAdminUserId).collect(Collectors.toList());
        Map<String, UserDO> userMap = userList.stream().collect(Collectors.toMap(UserDO::getId, p -> p));
        // 用户拥有的权限
        List<UserRoleCompanyDO> userRoleCompanyDOList = userRoleCompanyService.selectByUserIds(new ArrayList<>(userMap.keySet()), siteId);
        // 用户Id-有权限的用工单位List
        Map<String, List<UserRoleCompanyDO>> userIdMap = userRoleCompanyDOList.parallelStream()
                .collect(Collectors.groupingBy(UserRoleCompanyDO::getUserId));
        return roleMemberList.parallelStream().map(roleMemberListVO -> {
            // 在渠道表 且 角色为渠道 过滤
            if (channelUserIds.contains(roleMemberListVO.getMemberId()) && roleIds.contains(roleMemberListVO.getRoleId())) {
                return null;
            }
            // 根据用户角色获取人力角色
            HrUserVO hrUserVO = getHrUserByRoleMember(roleMemberListVO, userMap, siteId);
            if (Objects.isNull(hrUserVO)) {
                return null;
            }
            List<UserRoleCompanyDO> roleCompanyDOList = userIdMap.get(hrUserVO.getId());
            // 没有用工单位 显示：无
            if (CollectionUtils.isEmpty(roleCompanyDOList)) {
                hrUserVO.setCompanyName("无");
                hrUserVO.setIsAllEmployer(false);
                hrUserVO.setCompanyIdList(new ArrayList<>());
                return hrUserVO;
            }
            boolean isAllChildCompany = roleCompanyDOList.parallelStream().anyMatch(UserRoleCompanyDO::getIsAllChildCompany);
            if (isAllChildCompany) {
                hrUserVO.setCompanyName(permissionProviderService.getSiteName(siteId));
                // 站点下用工单位
                List<CompanyDO> companyDOList = companyService.selectBySiteId(siteId);
                List<String> companyNames = companyDOList.parallelStream().map(CompanyDO::getName).collect(Collectors.toList());
                // 站点下用工单位分组
                List<ChildCompanyDO> childCompanyDOList = childCompanyService.selectBySiteId(siteId);
                List<String> childCompanyNames = childCompanyDOList.parallelStream().map(ChildCompanyDO::getName).collect(Collectors.toList());
                companyNames.addAll(childCompanyNames);
                hrUserVO.setCompanyAllName(companyNames.parallelStream().collect(Collectors.joining(",")));
            } else {
                Set<String> companyAllName = new HashSet<>();
                for (UserRoleCompanyDO userRoleCompanyDO : roleCompanyDOList) {
                    if (userRoleCompanyDO.getIsAllEmployer()) {
                        // 用工单位分组
                        ChildCompanyVO childCompanyVO = childCompanyService.selectById(userRoleCompanyDO.getChildCompanyId(), siteId);
                        if (childCompanyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(childCompanyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(childCompanyVO.getName());
                        }
                    } else {
                        // 用工单位
                        CompanyVO companyVO = companyService.selectBaseCompanyById(userRoleCompanyDO.getEmployerId(), tokenUser.getSiteId());
                        if (companyVO != null) {
                            if (StringUtils.isBlank(hrUserVO.getCompanyName())) {
                                hrUserVO.setCompanyName(companyVO.getName() + (roleCompanyDOList.size() > 1 ? "等"
                                        + roleCompanyDOList.size() + "个" : ""));
                            }
                            companyAllName.add(companyVO.getName());
                        }
                    }
                }
                // 拥有的分组
                List<String> childCompanyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getChildCompanyId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                List<String> companyIdList = groupCompanyService.selectCompanyIdListByGroupIds(childCompanyIds, siteId);
                // 拥有的公司
                List<String> companyIds = roleCompanyDOList.parallelStream().map(UserRoleCompanyDO::getEmployerId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());
                companyIdList.addAll(companyIds);
                hrUserVO.setCompanyIdList(companyIdList);
                if (CollectionUtils.isEmpty(companyAllName)) {
                    hrUserVO.setCompanyAllName("无");
                } else {
                    hrUserVO.setCompanyAllName(companyAllName.parallelStream().collect(Collectors.joining(",")));
                }
            }
            hrUserVO.setIsAllEmployer(isAllChildCompany);
            return hrUserVO;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

}
